﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data;
using MySql.Data.MySqlClient;


namespace PACKETPARSERMAX20.CORE
{
    public class FactionEntry
    {
        public Int32 ID;                                         // 0
        public Int32 reputationListID;                           // 1
        public UInt32 BaseRepRaceMask1;                         // 2-5 Base reputation race masks (see enum Races)
        public UInt32 BaseRepRaceMask2;
        public UInt32 BaseRepRaceMask3;
        public UInt32 BaseRepRaceMask4;
        public UInt32 BaseRepClassMask1;                        // 6-9 Base reputation class masks (see enum Classes)
        public UInt32 BaseRepClassMask2;
        public UInt32 BaseRepClassMask3;
        public UInt32 BaseRepClassMask4;
        public Int32 BaseRepValue1;                            // 10-13 Base reputation values
        public Int32 BaseRepValue2;
        public Int32 BaseRepValue3;
        public Int32 BaseRepValue4;
        public UInt32 ReputationFlags1;                         // 14-17 Default flags to apply
        public UInt32 ReputationFlags2;
        public UInt32 ReputationFlags3;
        public UInt32 ReputationFlags4;
        public UInt32 team;                                       // 18 enum Team
        public string name;                                   // 19-34
        // 35 string flags, unused
        public string description;                            // 36-51 unused
        // 52 string flags, unused
    };

    public class FactionTemplateEntry
    {
        public Int32 ID;                                         // 0
        public Int32 faction;                                    // 1
        public UInt32 factionFlags;                               // 2 specific flags for that faction
        public UInt32 ourMask;                                    // 3 if mask set (see FactionMasks) then faction included in masked team
        public UInt32 friendlyMask;                               // 4 if mask set (see FactionMasks) then faction friendly to masked team
        public UInt32 hostileMask;                                // 5 if mask set (see FactionMasks) then faction hostile to masked team
        public UInt32 enemyFaction1;                              // 6
        public UInt32 enemyFaction2;                              // 7
        public UInt32 enemyFaction3;                              // 8
        public UInt32 enemyFaction4;                              // 9
        public UInt32 friendFaction1;                             // 10
        public UInt32 friendFaction2;                             // 11
        public UInt32 friendFaction3;                             // 12
        public UInt32 friendFaction4;                             // 13
        //-------------------------------------------------------  end structure

        // helpers
        public bool IsFriendlyTo(FactionTemplateEntry entry)
        {
            if (enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction)
                return false;
            if (friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction)
                return true;
            return (friendlyMask & entry.ourMask) > 0 || (ourMask & entry.friendlyMask) > 0;
        }
        public bool IsHostileTo(FactionTemplateEntry entry)
        {
            if (enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction)
                return true;
            if (friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction)
                return false;
            return (hostileMask & entry.ourMask) != 0;
        }
        public bool IsHostileToPlayers() { return (hostileMask & (uint)FactionMasks.FACTION_MASK_PLAYER) != 0; }
        public bool IsNeutralToAll() { return hostileMask == 0 && friendlyMask == 0 && enemyFaction1 == 0 && enemyFaction2 == 0 && enemyFaction3 == 0 && enemyFaction4 == 0; }
        public bool IsContestedGuardFaction() { return (factionFlags & (uint)FactionTemplateFlags.FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) != 0; }
    };

    public class FactionHandler
    {
        private int mClientBuild = 0;

        public FactionHandler(int build)
        {
            mClientBuild = build;
        }

        private object lockFactionEntryList = new object();
        private object lockFactionTemplateEntry  = new object();

        private System.Collections.Generic.SortedList<int, FactionEntry> mFactionEntryList = null;
        private System.Collections.Generic.SortedList<int, FactionTemplateEntry> mFactionTemplateEntry = null;

        public System.Collections.Generic.SortedList<int, FactionTemplateEntry> GetFactionTemplate()
        {
            lock (lockFactionTemplateEntry)
            {
                if (mFactionTemplateEntry == null)
                {

                    mFactionTemplateEntry = new SortedList<int, FactionTemplateEntry>();
                    using (var datatable = (new DBCDatabase("dbc_332", true)).ExecuteGetDataTable("select * from factiontemplate"))
                    {
                        foreach (System.Data.DataRow tRow in datatable.Rows)
                        {
                            FactionTemplateEntry tFactionTemplateEntry = new FactionTemplateEntry();
                            tFactionTemplateEntry.ID = tRow["id"].GetInt();
                            tFactionTemplateEntry.faction = tRow["ref_faction"].GetInt();
                            tFactionTemplateEntry.factionFlags = tRow["Flags"].GetUInt();
                            tFactionTemplateEntry.ourMask = tRow["ourMask"].GetUInt();
                            tFactionTemplateEntry.friendlyMask = tRow["friendlyMask"].GetUInt();
                            tFactionTemplateEntry.hostileMask = tRow["hostileMask"].GetUInt();
                            tFactionTemplateEntry.enemyFaction1 = tRow["enemy1"].GetUInt();
                            tFactionTemplateEntry.enemyFaction2 = tRow["enemy2"].GetUInt();
                            tFactionTemplateEntry.enemyFaction3 = tRow["enemy3"].GetUInt();
                            tFactionTemplateEntry.enemyFaction4 = tRow["enemy4"].GetUInt();
                            tFactionTemplateEntry.friendFaction1 = tRow["friend1"].GetUInt();
                            tFactionTemplateEntry.friendFaction2 = tRow["friend2"].GetUInt();
                            tFactionTemplateEntry.friendFaction3 = tRow["friend3"].GetUInt();
                            tFactionTemplateEntry.friendFaction4 = tRow["friend4"].GetUInt();
                            mFactionTemplateEntry.Add(tFactionTemplateEntry.ID, tFactionTemplateEntry);
                        }
                    }
                }
            }
            return mFactionTemplateEntry;
        }

        public FactionTemplateEntry GetFactionTemplate(int pID)
        {
            var t = GetFactionTemplate();

            if (t.ContainsKey(pID))
                return GetFactionTemplate()[pID];

            return null;
        }

        public System.Collections.Generic.SortedList<int, FactionEntry> GetFaction()
        {
            lock (lockFactionEntryList)
            {
                if (mFactionEntryList == null)
                {

                    mFactionEntryList = new SortedList<int, FactionEntry>();
                    using (var datatable = (new DBCDatabase("dbc_332", true)).ExecuteGetDataTable("select * from faction"))
                    {
                        foreach (System.Data.DataRow tRow in datatable.Rows)
                        {
                            FactionEntry tFactionEntry = new FactionEntry();

                            tFactionEntry.ID = tRow["id"].GetInt();
                            tFactionEntry.reputationListID = tRow["ReputationListId"].GetInt();
                            tFactionEntry.BaseRepRaceMask1 = tRow["BaseRaceMask1"].GetUInt();
                            tFactionEntry.BaseRepRaceMask2 = tRow["BaseRaceMask2"].GetUInt();
                            tFactionEntry.BaseRepRaceMask3 = tRow["BaseRaceMask3"].GetUInt();
                            tFactionEntry.BaseRepRaceMask4 = tRow["BaseRaceMask4"].GetUInt();
                            tFactionEntry.BaseRepClassMask1 = tRow["BaseClassMask1"].GetUInt();
                            tFactionEntry.BaseRepClassMask2 = tRow["BaseClassMask2"].GetUInt();
                            tFactionEntry.BaseRepClassMask3 = tRow["BaseClassMask3"].GetUInt();
                            tFactionEntry.BaseRepClassMask4 = tRow["BaseClassMask4"].GetUInt();
                            tFactionEntry.BaseRepValue1 = tRow["BaseRepValue1"].GetInt();
                            tFactionEntry.BaseRepValue2 = tRow["BaseRepValue2"].GetInt();
                            tFactionEntry.BaseRepValue3 = tRow["BaseRepValue3"].GetInt();
                            tFactionEntry.BaseRepValue4 = tRow["BaseRepValue4"].GetInt();
                            tFactionEntry.ReputationFlags1 = tRow["Flags1"].GetUInt();
                            tFactionEntry.ReputationFlags2 = tRow["Flags2"].GetUInt();
                            tFactionEntry.ReputationFlags3 = tRow["Flags3"].GetUInt();
                            tFactionEntry.ReputationFlags4 = tRow["Flags4"].GetUInt();
                            tFactionEntry.team = tRow["ParentTeamFaction"].GetUInt();
                            tFactionEntry.name = (string)tRow["FactionName"];
                            tFactionEntry.description = (string)tRow["Description"];

                            mFactionEntryList.Add(tFactionEntry.ID, tFactionEntry);
                        }
                    }
                }
            }
            return mFactionEntryList;
        }


        public FactionEntry GetFaction(int pID)
        {
            var t = GetFaction();

            if (t.ContainsKey(pID))
                return GetFaction()[pID];

            return null;
        }
    }
}
